/**
 * Copyright 1996 self.com.au
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License. (http://www.apache.org/licenses/LICENSE-2.0)
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed 
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for 
 * the specific language governing permissions and limitations under the License.
 *
 * <dhamma-message src="Atisha (11th century Tibetan Buddhist master)">
 * 	The greatest achievement is selflessness. The greatest worth is self-mastery.
 * 	The greatest quality is seeking to serve others. The greatest precept is continual awareness.
 * 	The greatest medicine is the emptiness of everything. The greatest action is not conforming with the worlds ways.
 * 	The greatest magic is transmuting the passions. The greatest generosity is non-attachment.
 * 	The greatest goodness is a peaceful mind. The greatest patience is humility.
 * 	The greatest effort is not concerned with results. The greatest meditation is a mind that lets go.
 * 	The greatest wisdom is seeing through appearances. 
 * </dhamma-message>
 *
 * @author Ashin Wimalajeewa
 *
 * Note, this is a very old runtime library that I have evolved since 1996. I rarely use it
 * now because the Apache Commons project has made it obsolete.
 */
package self.xml;

import self.lang.*;

final public class SpecialCharacterUtils {
  final static public int LESS_THAN_MASK = 1;
  final static public int GREATER_THAN_MASK = LESS_THAN_MASK << 1;
  final static public int AMP_MASK = GREATER_THAN_MASK << 1;
  final static public int APOS_MASK = AMP_MASK << 1;
  final static public int QUOTE_MASK = APOS_MASK << 1;
  final static public int NEW_LINE_MASK = QUOTE_MASK << 1;

  final static public String XML_LESS_THAN = "&lt;";
  final static public String XML_GREATER_THAN = "&gt;";
  final static public String XML_AMP = "&amp;";
  final static public String XML_APOS = "&#39;"; // &apos;
  final static public String XML_QUOTE = "&quot;";
  final static public String XHTML_NEW_LINE = "<br/>";

  final static public char cUTF_LESS_THAN = '<';
  final static public char cUTF_GREATER_THAN = '>';
  final static public char cUTF_AMP = '&';
  final static public char cUTF_APOS = '\'';
  final static public char cUTF_QUOTE = '"';
  final static public char cUTF_NEW_LINE = '\n';

  final static public String UTF_LESS_THAN = cUTF_LESS_THAN + "";
  final static public String UTF_GREATER_THAN = cUTF_GREATER_THAN + "";
  final static public String UTF_AMP = cUTF_AMP + "";
  final static public String UTF_APOS = cUTF_APOS + "";
  final static public String UTF_QUOTE = cUTF_QUOTE + "";

  final static public int CORE = LESS_THAN_MASK | GREATER_THAN_MASK |
                                              AMP_MASK | APOS_MASK | QUOTE_MASK;
  final static public int ALL = CORE | NEW_LINE_MASK;

  final static public int CORE_EXCEPT_AMP = CORE ^ AMP_MASK;
  final static public int CORE_EXCEPT_AMP_APOS = CORE_EXCEPT_AMP ^ APOS_MASK;

  private SpecialCharacterUtils() {
	// nothing to do.
  }

  static public String encode( String data ) {
    StringBuffer buff = new StringBuffer( data );
    encodeTextBuffer( buff, CORE );
    return buff.toString();
  }

  static public String decode( String data ) {
    data = StringUtils.replace( data, XML_LESS_THAN, UTF_LESS_THAN );
    data = StringUtils.replace( data, XML_GREATER_THAN, UTF_GREATER_THAN );
    data = StringUtils.replace( data, XML_APOS, UTF_APOS );
    data = StringUtils.replace( data, XML_QUOTE, UTF_QUOTE );
    data = StringUtils.replace( data, XML_AMP, UTF_AMP );
    return data;
  }

  static public void encodeTextBuffer( StringBuffer buff ) {
    encodeTextBuffer( buff, ALL );
  }

  static public void encodeTextBuffer( StringBuffer buff, int encodeKinds ) {
    boolean newLine = (encodeKinds & NEW_LINE_MASK) != 0;
    boolean lessThan = (encodeKinds & LESS_THAN_MASK) != 0;
    boolean greaterThan = (encodeKinds & GREATER_THAN_MASK) != 0;
    boolean apos = (encodeKinds & APOS_MASK) != 0;
    boolean quote = (encodeKinds & QUOTE_MASK) != 0;
    boolean amp = (encodeKinds & AMP_MASK) != 0;

    String value = buff.toString();
    char content[] = new char[value.length()];
    value.getChars(0, value.length(), content, 0);
    StringBuffer result = new StringBuffer(content.length + 50);
    for (int i = 0; i < content.length; i++) {
      boolean addChar = false;
      switch (content[i]) {
        case cUTF_NEW_LINE :
          if ( newLine )
            result.append( XHTML_NEW_LINE );
          else
            addChar = true;
          break;
        case cUTF_LESS_THAN:
          if ( lessThan )
            result.append( XML_LESS_THAN );
          else
            addChar = true;
          break;
        case cUTF_GREATER_THAN:
          if ( greaterThan )
            result.append( XML_GREATER_THAN );
          else
            addChar = true;
          break;
        case cUTF_AMP:
          if ( amp )
            result.append( XML_AMP );
          else
            addChar = true;
          break;
        case cUTF_QUOTE:
          if ( quote )
            result.append( XML_QUOTE );
          else
            addChar = true;
          break;
        case cUTF_APOS:
          if ( apos )
            result.append( XML_APOS );
          else
            addChar = true;
          break;
        default:
          addChar = true;
      }
      if ( addChar )
        result.append(content[i]);
    }
    buff.delete( 0, value.length() );
    buff.append( result.toString() );
  }

//  static public void main( String[] args ) {
//    String test = "'I <love> \"c++\" & delphi'";
//    StringBuffer b = new StringBuffer( test );
//    StringBuffer b2 = new StringBuffer( b.toString() );
//
//    encodeTextBuffer( b );
//System.out.println("b=" + b );
//    encodeTextBuffer( b2, LESS_THAN_MASK | GREATER_THAN_MASK );
//System.out.println("b2=" + b2 );
//  }
}